/**
 * Created by scenic on 2017/8/10.
 */
import {MeshCreateUtils as CreateMeshUtils} from "./MeshCreateUtils";
import {SpaceFace} from "./SpaceFace";
/**
 * 确定了空间的尺寸和位置信息，空间的面是需要根据mesh来决定的
 * 1. 计算出空间自身的大小和位置
 * 2. 根据线性分割计算出子空间的尺寸和位置
 * 3. 更新空间的mesh
 * 4. 更新空间的面的信息
 * 5. 更新面对应的木板信息
 * @param width
 * @param height
 * @param depth
 * @constructor
 */

function Space(width, height, depth) {
    this.id = Space.prototype.ID++;
    this.name = "空间:" + this.id;
    //空间的概念，应该是一个树形的结构，是可以嵌套的，同时需要满足父空间的大小要能覆盖子空间的大小
    this.parent = null;
    //子空间数组
    this.children_space = [];
    //用来图形化显示
    this.spaceMesh = undefined;

    this.position = new THREE.Vector3();

    Object.defineProperty(this, "width", {
        get: function () {
            return this.dimension.x;
        },
        set: function (v) {
            this.dimension.setX(v);
        }
    })

    Object.defineProperty(this, "height", {
        get: function () {
            return this.dimension.y;
        }
        ,
        set: function (v) {
            this.dimension.setY(v);
        }
    })

    Object.defineProperty(this, "depth", {
        get: function () {
            return this.dimension.z;
        }
        ,
        set: function (v) {
            this.dimension.setZ(v);
        }
    })
    //线性分割
    this.segment = undefined;
    //线性分割的方向
    this.segmentOrientation = undefined;
    //分割的角度
    this.segmentEuler = undefined;

    //空间虽有的面，用来关联木板的
    this.faces = [];

    this.updateSegmentInterface = undefined;
}

Space.prototype = Object.assign({
    constructor: Space,
    ID: 0,
    add: function (space) {
        this.children_space.push(space);
        space.parent = this;
    },

    /**
     *  remove 有两个层面
     *  1. 删除Space的孩子
     *  2. 标记所有被删除的mesh，方便再绘制的时候可以把不用的mesh删除
     * @param start
     * @param end
     */
    remove: function (start, end) {
        var children = this.children_space;
        end = (end == undefined) ? children.length : end;

        var notUsedArray = children.splice(start, end);

        //同时应该删除scene中的对应的mesh
        notUsedArray.forEach(function (spaceParent) {
            spaceParent.traverse(function (space) {
                space.parent = null;
                if (space.spaceMesh) {
                    space.spaceMesh.associateHost = undefined;
                }
            })
        })
    },

    /**
     * 设置线性分割
     * @param _segment
     * @param orientation  分割的方向
     */
    setSegment: function (_segment, orientation) {
        this.segment = _segment;
        this.segmentOrientation = orientation;
    },

    traverse: function (callback, recursion) {
        callback.call(this, this);

        if (recursion !== false) {
            var children = this.children_space;
            for (var i = 0; i < children.length; i++) {
                children[i].traverse(callback);
            }
        }
    },

    toTreeFolder: function () {
        var result = new GSThree.Folder(this);

        this.faces.forEach(function (face) {
            result.add(new GSThree.File(face));
        })

        this.children_space.forEach(function (children) {
            var childrenFolder = children.toTreeFolder();
            result.add(childrenFolder);
        })
        return result;
    },

    /**
     *
     * @param direction
     */
    getBeginFaceByDirection: function (direction) {
        var minFace = undefined;
        var tmpV = new THREE.Vector3();
        this.faces.forEach(function (face) {
            if (minFace == undefined) {
                minFace = face;
            }
            var minValue = tmpV.copy(minFace.box3.getCenter()).dot(direction);
            var curValue = tmpV.copy(face.box3.getCenter()).dot(direction);
            if (minValue > curValue) {
                minFace = face;
            }
        })
        return minFace;
    },
    getAssociateMesh: function () {
        return this.spaceMesh;
    },
    getRoot: function () {
        var root = this;
        while (root.parent != null) {
            root = root.parent;
        }
        return root;

    },

    notifyDimensionUpdate:function () {
        this.updateSegment();
    },
    addMeshToScene:function (scene) {
        scene.add(this.spaceMesh);
    },

    //更新空间的mesh和空间的面的信息
    updateSpaceMeshAndFaces: function () {
        if (this.spaceMesh == undefined) {
            this.spaceMesh = CreateMeshUtils.createSpaceMesh().setName(this.name);
        }

        var mesh = this.spaceMesh;
        mesh.scaleToDimension(this.dimension);
        mesh.position.copy(this.position);

        //根据SpaceMesh的空间信息，更新 faces的集合
        var faces = this.faces;
        mesh.updateMatrixWorld(true);
        var geometry = mesh.geometry;
        geometry.computeFaces();
        var facesOfGeometry = geometry.faces;

        for (var i = 0, j = 0; i < facesOfGeometry.length - 1; i += 2, j++) {
            if (faces[j] == undefined) {
                faces[j] = new SpaceFace(this, "name" + j);
            }
            var spaceFace = faces[j];
            //计算出面的尺寸，中心点
            var face1 = facesOfGeometry[i];
            var face2 = facesOfGeometry[i + 1];
            var vertices = geometry.vertices;
            var matrixWorld = mesh.matrixWorld;
            spaceFace.initialize(face1, face2, vertices, matrixWorld);
        }

        if(this.segment !== undefined){
            this.spaceMesh.visible = false;
        }
    },
    updateSegment:function () {
        throw  new Error("this function must be implement in children")
    },
})

export {Space}